package com.platform.module.common.utils;

import com.platform.module.common.base.CodeEnum;
import com.platform.module.common.exception.CommonException;
import com.platform.module.common.exception.SystemCommonResult;
import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
import java.util.Optional;

/**
 * 断言工具类
 */
public class AssertUtils {

    /**
     * 抛出业务流程终止消息异常
     *
     * @param code 消息代码
     * @param args 消息变量
     */
    public static void throwMsg(String code, Object... args) {
        throw getMsgException(code, args);
    }

    /**
     * 抛出业务流程终止消息异常
     *
     * @param code 消息枚举
     */
    public static void throwMsg(CodeEnum code) {
        throw getMsgException(code);
    }

    /**
     * 抛出业务流程终止消息异常
     *
     * @param code 消息枚举
     * @param args 消息变量
     */
    public static void throwMsg(CodeEnum code, Object... args) {
        throw getMsgException(code, args);
    }

    /**
     * 获取一个业务流程终止消息异常对象
     *
     * @param code 消息代码
     * @param args 消息变量
     */
    public static CommonException getMsgException(String code, Object... args) {
        return new CommonException(new SystemCommonResult(code, MessageUtils.getMsg(code, args)));
    }

    /**
     * 获取一个业务流程终止消息异常对象
     *
     * @param code 消息枚举
     */
    public static CommonException getMsgException(CodeEnum code) {
        return new CommonException(code);
    }

    /**
     * 获取一个业务流程终止消息异常对象
     *
     * @param code 消息枚举
     * @param args 消息变量
     */
    public static CommonException getMsgException(CodeEnum code, Object... args) {
        return new CommonException(code, args);
    }

    /**
     * 断言表达式结果为真
     *
     * @param express 表达式
     * @param code    消息代码
     * @param args    消息变量
     */
    public static void assertTrue(Boolean express, String code, Object... args) {
        if (express == null || !express) {
            throwMsg(code, args);
        }
    }

    /**
     * 断言表达式结果为真
     *
     * @param express 表达式
     * @param code    消息枚举
     */
    public static void assertTrue(Boolean express, CodeEnum code) {
        if (express == null || !express) {
            throwMsg(code);
        }
    }

    /**
     * 断言表达式结果为真
     *
     * @param express 表达式
     * @param code    消息枚举
     * @param args    消息变量
     */
    public static void assertTrue(Boolean express, CodeEnum code, Object... args) {
        if (express == null || !express) {
            throwMsg(code, args);
        }
    }

    /**
     * 断言表达式结果为假
     *
     * @param express 表达式
     * @param code    消息代码
     * @param args    消息变量
     */
    public static void assertFalse(Boolean express, String code, Object... args) {
        assertTrue(express != null && !express, code, args);
    }

    /**
     * 断言一致
     *
     * @param target 欲比较的对象
     * @param other  与之比较的对象
     * @param code   消息代码
     * @param args   消息变量
     */
    public static void assertEquals(Object target, Object other, String code, Object... args) {
        assertTrue(Objects.equals(target, other), code, args);
    }

    /**
     * 断言一致
     *
     * @param target 欲比较的对象
     * @param other  与之比较的对象
     * @param code   消息枚举
     */
    public static void assertEquals(Object target, Object other, CodeEnum code) {
        assertTrue(Objects.equals(target, other), code);
    }

    /**
     * 断言不一致
     *
     * @param target 欲比较的对象
     * @param other  与之比较的对象
     * @param code   消息代码
     * @param args   消息变量
     */
    public static void assertNotEquals(Object target, Object other, String code, Object... args) {
        assertTrue(!Objects.equals(target, other), code, args);
    }


    /**
     * 断言不一致
     *
     * @param target 欲比较的对象
     * @param other  与之比较的对象
     * @param code   消息枚举
     */
    public static void assertNotEquals(Object target, Object other, CodeEnum code) {
        assertTrue(!Objects.equals(target, other), code);
    }

    /**
     * 断言大于
     *
     * @param target 欲比较的对象
     * @param other  与之比较的对象
     * @param code   消息代码
     * @param args   消息变量
     */
    public static <T> void assertGt(Comparable<T> target, T other, String code, Object... args) {
        assertTrue(target.compareTo(other) > 0, code, args);
    }

    /**
     * 断言大于
     *
     * @param target 欲比较的对象
     * @param other  与之比较的对象
     * @param code   消息枚举
     */
    public static <T> void assertGt(Comparable<T> target, T other, CodeEnum code) {
        assertTrue(target.compareTo(other) > 0, code);
    }

    /**
     * 断言大于
     *
     * @param target 欲比较的对象
     * @param other  与之比较的对象
     * @param code   消息枚举
     * @param args   消息变量
     */
    public static <T> void assertGt(Comparable<T> target, T other, CodeEnum code, Object... args) {
        assertTrue(target.compareTo(other) > 0, code, args);
    }

    /**
     * 断言大于等于
     *
     * @param target 欲比较的对象
     * @param other  与之比较的对象
     * @param code   消息代码
     * @param args   消息变量
     */
    public static <T> void assertGe(Comparable<T> target, T other, String code, Object... args) {
        assertTrue(target.compareTo(other) >= 0, code, args);
    }


    /**
     * 断言大于等于
     *
     * @param target 欲比较的对象
     * @param other  与之比较的对象
     * @param code   消息枚举
     * @param args   消息变量
     */
    public static <T> void assertGe(Comparable<T> target, T other, CodeEnum code, Object... args) {
        assertTrue(target.compareTo(other) >= 0, code, args);
    }

    /**
     * 断言小于
     *
     * @param target 欲比较的对象
     * @param other  与之比较的对象
     * @param code   消息代码
     * @param args   消息变量
     */
    public static <T> void assertLt(Comparable<T> target, T other, String code, Object... args) {
        assertTrue(target.compareTo(other) < 0, code, args);
    }

    /**
     * 断言小于
     *
     * @param target 欲比较的对象
     * @param other  与之比较的对象
     * @param code   消息枚举
     */
    public static <T> void assertLt(Comparable<T> target, T other, CodeEnum code) {
        assertTrue(target.compareTo(other) < 0, code);
    }

    /**
     * 断言小于等于
     *
     * @param target 欲比较的对象
     * @param other  与之比较的对象
     * @param code   消息代码
     * @param args   消息变量
     */
    public static <T> void assertLe(Comparable<T> target, T other, String code, Object... args) {
        assertTrue(target.compareTo(other) <= 0, code, args);
    }

    /**
     * 断言等于
     *
     * @param target 欲比较的对象
     * @param other  与之比较的对象
     * @param code   消息代码
     * @param args   消息变量
     */
    public static <T> void assertEq(Comparable<T> target, T other, String code, Object... args) {
        assertTrue(target.compareTo(other) == 0, code, args);
    }

    /**
     * 断言为空
     *
     * @param target 目标对象
     * @param code   消息代码
     * @param args   消息变量
     */
    public static void assertNull(Object target, String code, Object... args) {
        assertTrue(target == null, code, args);
    }

    /**
     * 断言非空
     *
     * @param target 目标对象
     * @param code   消息代码
     * @param args   消息变量
     * @return 返回经过非空验证的值
     */
    public static <T> T assertNotNull(T target, String code, Object... args) {
        assertTrue(target != null, code, args);
        return target;
    }

    /**
     * 断言非空
     *
     * @param target 目标对象
     * @param code   消息枚举
     * @return 返回经过非空验证的值
     */
    public static <T> T assertNotNull(T target, CodeEnum code) {
        assertTrue(target != null, code);
        return target;
    }

    /**
     * 断言非空
     *
     * @param target 目标对象
     * @param code   消息枚举
     * @param args   消息变量
     * @return 返回经过非空验证的值
     */
    public static <T> T assertNotNull(T target, CodeEnum code, Object... args) {
        assertTrue(target != null, code, args);
        return target;
    }

    /**
     * 断言 Optional 为空
     *
     * @param target 目标对象
     * @param code   消息代码
     * @param args   消息变量
     */
    public static void assertNull(Optional<?> target, String code, Object... args) {
        assertTrue(target == null || !target.isPresent(), code, args);
    }

    /**
     * 断言为空
     *
     * @param target 目标对象
     * @param code   消息枚举
     * @return 返回经过非空验证的值
     */
    public static <T> T assertNull(T target, CodeEnum code) {
        assertTrue(target == null, code);
        return target;
    }

    /**
     * 断言 Optional 非空
     *
     * @param target 目标对象
     * @param code   消息代码
     * @param args   消息变量
     * @return 返回经过非空验证的值
     */
    public static <T> T assertNotNull(Optional<T> target, String code, Object... args) {
        assertTrue(target != null && target.isPresent(), code, args);
        return target.get();
    }

    /**
     * 断言字符串非null也非空
     *
     * @param target 目标对象
     * @param code   消息代码
     * @param args   消息变量
     */
    public static String assertNotEmpty(String target, String code, Object... args) {
        assertTrue(StringUtils.isNotEmpty(target), code, args);
        return target;
    }

    /**
     * 断言字符串为null或为空
     *
     * @param target 目标对象
     * @param code   消息代码
     * @param args   消息变量
     */
    public static void assertEmpty(String target, String code, Object... args) {
        assertTrue(StringUtils.isEmpty(target), code, args);
    }

    /**
     * 断言字符串为null或为空
     *
     * @param target 目标对象
     * @param code   消息枚举
     */
    public static void assertEmpty(String target, CodeEnum code) {
        assertTrue(StringUtils.isEmpty(target), code);
    }

    /**
     * 断言集合非空
     *
     * @param target 目标对象
     * @param code   消息代码
     * @param args   消息变量
     */
    public static <C extends Collection<T>, T> C assertNotEmpty(C target, String code, Object... args) {
        assertTrue(target != null && !target.isEmpty(), code, args);
        return target;
    }

    /**
     * 断言集合非空
     *
     * @param target 目标对象
     * @param code   消息枚举
     */
    public static <C extends Collection<T>, T> C assertNotEmpty(C target, CodeEnum code) {
        assertTrue(target != null && !target.isEmpty(), code);
        return target;
    }

    /**
     * 断言集合为null或为空
     *
     * @param target 目标对象
     * @param code   消息代码
     * @param args   消息变量
     */
    public static void assertEmpty(Collection<?> target, String code, Object... args) {
        assertTrue(target == null || target.isEmpty(), code, args);
    }

    /**
     * 断言集合为null或为空
     *
     * @param target 目标对象
     * @param code   消息枚举
     */
    public static void assertEmpty(Collection<?> target, CodeEnum code) {
        assertTrue(target == null || target.isEmpty(), code);
    }


    /**
     * 断言字符串非空也非全部空
     *
     * @param target 目标对象
     * @param code   消息代码
     * @param args   消息变量
     */
    public static String assertNotBlank(String target, String code, Object... args) {
        assertTrue(StringUtils.isNotBlank(target), code, args);
        return target;
    }

    /**
     * 断言字符串为空或全部为空
     *
     * @param target 目标对象
     * @param code   消息代码
     * @param args   消息变量
     */
    public static void assertBlank(String target, String code, Object... args) {
        assertTrue(StringUtils.isBlank(target), code, args);
    }

    /**
     * 断言在组中
     *
     * @param target 目标对象
     * @param array  数组
     * @param code   消息代码
     * @param args   消息变量
     */
    public static void assertIn(Object target, Object[] array, String code, Object... args) {
        assertTrue(Arrays.asList(array).contains(target), code, args);
    }
}
